#include "threadPool.h"

int transFile(int netfd, cmd_t Cmd)
{
    // 打开文件之前需要先获取文件在本地的真实名称
    int code;
    int user_id = client_id[netfd];
    get_user_code(user_id, &code);
    char md5_str[MD5_STR_LEN + 1] = {0};
    get_fsystem_md5(Cmd.object, user_id, code, md5_str); // 根据文件名、user_id和用户当前目录id，在虚拟文件表中找到md5值
    char real_file_name[1024] = {0};
    get_real_file_name(md5_str, real_file_name); // 根据文件名md5值获取本地的真实文件名
    char path[1024] = {0};
    sprintf(path, "%s%s%s", "Netdisk", "/", real_file_name); // 拼出文件本地地址
    int fd = open(path, O_RDWR);                             // 打开本地文件
    // printf("path = %s\n", path);
    train_t train;
    if (fd == -1) // 打开文件错误需要通知对面
    {
        perror("open");
        bzero(&train, sizeof(train));
        train.length = 0;
        send(netfd, &train, sizeof(train.length) + train.length, 0);
    }
    // 将文件名通过火车发送
    bzero(&train, sizeof(train));
    train.length = strlen(Cmd.object);
    memcpy(train.data, Cmd.object, strlen(Cmd.object));
    send(netfd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    // 获取文件长度，并将其装入火车发送
    struct stat statbuf;
    fstat(fd, &statbuf);
    bzero(&train, sizeof(train));
    train.length = sizeof(statbuf.st_size);
    memcpy(train.data, &statbuf.st_size, sizeof(statbuf.st_size));
    // 先发送原文件大小
    send(netfd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    off_t remainSize = statbuf.st_size - Cmd.offset;
    printf("remian size = %ld\n", remainSize);

    long totalSize = Cmd.offset; // 已传大小
    char *p = (char *)mmap(NULL, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    ERROR_CHECK(p, MAP_FAILED, "mmap");
    if (statbuf.st_size >= 1073741824) // 大于1G,一次性传送
    {
        send(netfd, p, statbuf.st_size, MSG_NOSIGNAL);
        printf("send once!\n");
    }
    else
    { // 文件小于1G，先mmap再send
        printf("send with mmap\n");
        while (totalSize < statbuf.st_size)
        {
            if (statbuf.st_size - totalSize > sizeof(train.data))
            {
                train.length = sizeof(train.data);
            }
            else
            {
                train.length = statbuf.st_size - totalSize;
            }
            memcpy(train.data, p + totalSize, train.length);
            totalSize += train.length;
            send(netfd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
        }
        train.length = 0;
        send(netfd, &train, sizeof(train.length) + train.length, MSG_NOSIGNAL);
    }
    close(fd);
    munmap(p, statbuf.st_size);
    return 0;
}